


using System;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using SubSonic.DataProviders;
using SubSonic.Extensions;
using SubSonic.Linq.Structure;
using SubSonic.Query;
using SubSonic.Schema;
using System.Data.Common;
using System.Collections.Generic;

namespace Entities
{
	public partial class BemEstarEmpregoDB : IQuerySurface
	{

		public IDataProvider DataProvider;
		public DbQueryProvider provider;

		public static IDataProvider DefaultDataProvider { get; set; }

		public bool TestMode
		{
			get
			{
				return DataProvider.ConnectionString.Equals("test", StringComparison.InvariantCultureIgnoreCase);
			}
		}

		public BemEstarEmpregoDB()
		{
			if (DefaultDataProvider == null)
			{
				DataProvider = ProviderFactory.GetProvider("bemestar");
			}
			else
			{
				DataProvider = DefaultDataProvider;
			}
			Init();
		}

		public BemEstarEmpregoDB(string connectionStringName)
		{
			DataProvider = ProviderFactory.GetProvider(connectionStringName);
			Init();
		}

		public BemEstarEmpregoDB(string connectionString, string providerName)
		{
			DataProvider = ProviderFactory.GetProvider(connectionString, providerName);
			Init();
		}

		public ITable FindByPrimaryKey(string pkName)
		{
			return DataProvider.Schema.Tables.SingleOrDefault(x => x.PrimaryKey.Name.Equals(pkName, StringComparison.InvariantCultureIgnoreCase));
		}

		public Query<T> GetQuery<T>()
		{
			return new Query<T>(provider);
		}

		public ITable FindTable(string tableName)
		{
			return DataProvider.FindTable(tableName);
		}

		public IDataProvider Provider
		{
			get { return DataProvider; }
			set { DataProvider = value; }
		}

		public DbQueryProvider QueryProvider
		{
			get { return provider; }
		}

		BatchQuery _batch = null;
		public void Queue<T>(IQueryable<T> qry)
		{
			if (_batch == null)
				_batch = new BatchQuery(Provider, QueryProvider);
			_batch.Queue(qry);
		}

		public void Queue(ISqlQuery qry)
		{
			if (_batch == null)
				_batch = new BatchQuery(Provider, QueryProvider);
			_batch.Queue(qry);
		}

		public void ExecuteTransaction(IList<DbCommand> commands)
		{
			if (!TestMode)
			{
				using (var connection = commands[0].Connection)
				{
					if (connection.State == ConnectionState.Closed)
						connection.Open();

					using (var trans = connection.BeginTransaction())
					{
						foreach (var cmd in commands)
						{
							cmd.Transaction = trans;
							cmd.Connection = connection;
							cmd.ExecuteNonQuery();
						}
						trans.Commit();
					}
					connection.Close();
				}
			}
		}

		public IDataReader ExecuteBatch()
		{
			if (_batch == null)
				throw new InvalidOperationException("There's nothing in the queue");
			if (!TestMode)
				return _batch.ExecuteReader();
			return null;
		}

		public Query<Tcandidato_vaga> Tcandidato_vagas { get; set; }
		public Query<Tcategorium> Tcategoria { get; set; }
		public Query<Tcategoria_vaga> Tcategoria_vagas { get; set; }
		public Query<Tcnh> Tcnhs { get; set; }
		public Query<Tcolaborador> Tcolaboradors { get; set; }
		public Query<Tconhecimento_extra> Tconhecimento_extras { get; set; }
		public Query<Tcurso> Tcursos { get; set; }
		public Query<Tempresa> Tempresas { get; set; }
		public Query<Tendereco> Tenderecos { get; set; }
		public Query<Tescolaridade> Tescolaridades { get; set; }
		public Query<Texperiencium> Texperiencia { get; set; }
		public Query<Tidioma> Tidiomas { get; set; }
		public Query<Tincentivo> Tincentivos { get; set; }
		public Query<Tincentivo_vaga> Tincentivo_vagas { get; set; }
		public Query<Tperfil> Tperfils { get; set; }
		public Query<Tpessoa> Tpessoas { get; set; }
		public Query<Ttipo_usuario> Ttipo_usuarios { get; set; }
		public Query<Tusuario> Tusuarios { get; set; }
		public Query<Tvaga> Tvagas { get; set; }



		#region ' Aggregates and SubSonic Queries '
		public Select SelectColumns(params string[] columns)
		{
			return new Select(DataProvider, columns);
		}

		public Select Select
		{
			get { return new Select(this.Provider); }
		}

		public Insert Insert
		{
			get { return new Insert(this.Provider); }
		}

		public Update<T> Update<T>() where T : new()
		{
			return new Update<T>(this.Provider);
		}

		public SqlQuery Delete<T>(Expression<Func<T, bool>> column) where T : new()
		{
			LambdaExpression lamda = column;
			SqlQuery result = new Delete<T>(this.Provider);
			result = result.From<T>();
			result.Constraints = lamda.ParseConstraints().ToList();
			return result;
		}

		public SqlQuery Max<T>(Expression<Func<T, object>> column)
		{
			LambdaExpression lamda = column;
			string colName = lamda.ParseObjectValue();
			string objectName = typeof(T).Name;
			string tableName = DataProvider.FindTable(objectName).Name;
			return new Select(DataProvider, new Aggregate(colName, AggregateFunction.Max)).From(tableName);
		}

		public SqlQuery Min<T>(Expression<Func<T, object>> column)
		{
			LambdaExpression lamda = column;
			string colName = lamda.ParseObjectValue();
			string objectName = typeof(T).Name;
			string tableName = this.Provider.FindTable(objectName).Name;
			return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Min)).From(tableName);
		}

		public SqlQuery Sum<T>(Expression<Func<T, object>> column)
		{
			LambdaExpression lamda = column;
			string colName = lamda.ParseObjectValue();
			string objectName = typeof(T).Name;
			string tableName = this.Provider.FindTable(objectName).Name;
			return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Sum)).From(tableName);
		}

		public SqlQuery Avg<T>(Expression<Func<T, object>> column)
		{
			LambdaExpression lamda = column;
			string colName = lamda.ParseObjectValue();
			string objectName = typeof(T).Name;
			string tableName = this.Provider.FindTable(objectName).Name;
			return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Avg)).From(tableName);
		}

		public SqlQuery Count<T>(Expression<Func<T, object>> column)
		{
			LambdaExpression lamda = column;
			string colName = lamda.ParseObjectValue();
			string objectName = typeof(T).Name;
			string tableName = this.Provider.FindTable(objectName).Name;
			return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Count)).From(tableName);
		}

		public SqlQuery Variance<T>(Expression<Func<T, object>> column)
		{
			LambdaExpression lamda = column;
			string colName = lamda.ParseObjectValue();
			string objectName = typeof(T).Name;
			string tableName = this.Provider.FindTable(objectName).Name;
			return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Var)).From(tableName);
		}

		public SqlQuery StandardDeviation<T>(Expression<Func<T, object>> column)
		{
			LambdaExpression lamda = column;
			string colName = lamda.ParseObjectValue();
			string objectName = typeof(T).Name;
			string tableName = this.Provider.FindTable(objectName).Name;
			return new Select(this.Provider, new Aggregate(colName, AggregateFunction.StDev)).From(tableName);
		}

		#endregion

		void Init()
		{
			provider = new DbQueryProvider(this.Provider);

			#region ' Query Defs '
			Tcandidato_vagas = new Query<Tcandidato_vaga>(provider);
			Tcategoria = new Query<Tcategorium>(provider);
			Tcategoria_vagas = new Query<Tcategoria_vaga>(provider);
			Tcnhs = new Query<Tcnh>(provider);
			Tcolaboradors = new Query<Tcolaborador>(provider);
			Tconhecimento_extras = new Query<Tconhecimento_extra>(provider);
			Tcursos = new Query<Tcurso>(provider);
			Tempresas = new Query<Tempresa>(provider);
			Tenderecos = new Query<Tendereco>(provider);
			Tescolaridades = new Query<Tescolaridade>(provider);
			Texperiencia = new Query<Texperiencium>(provider);
			Tidiomas = new Query<Tidioma>(provider);
			Tincentivos = new Query<Tincentivo>(provider);
			Tincentivo_vagas = new Query<Tincentivo_vaga>(provider);
			Tperfils = new Query<Tperfil>(provider);
			Tpessoas = new Query<Tpessoa>(provider);
			Ttipo_usuarios = new Query<Ttipo_usuario>(provider);
			Tusuarios = new Query<Tusuario>(provider);
			Tvagas = new Query<Tvaga>(provider);
			#endregion


			#region ' Schemas '
			if (DataProvider.Schema.Tables.Count == 0)
			{
				DataProvider.Schema.Tables.Add(new Tcandidato_vagaTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TcategoriaTable(DataProvider));
				DataProvider.Schema.Tables.Add(new Tcategoria_vagaTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TcnhTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TcolaboradorTable(DataProvider));
				DataProvider.Schema.Tables.Add(new Tconhecimento_extraTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TcursoTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TempresaTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TenderecoTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TescolaridadeTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TexperienciaTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TidiomaTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TincentivoTable(DataProvider));
				DataProvider.Schema.Tables.Add(new Tincentivo_vagaTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TperfilTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TpessoaTable(DataProvider));
				DataProvider.Schema.Tables.Add(new Ttipo_usuarioTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TusuarioTable(DataProvider));
				DataProvider.Schema.Tables.Add(new TvagaTable(DataProvider));
			}
			#endregion
		}


		#region ' Helpers '

		internal static DateTime DateTimeNowTruncatedDownToSecond()
		{
			var now = DateTime.Now;
			return now.AddTicks(-now.Ticks % TimeSpan.TicksPerSecond);
		}

		#endregion

	}
}